import Coords from "./Coords";
import type World from "./World";
import hit_test from "./hit_test";
import rand from "./rand";

export default class Particle {
  private lifetime = rand(1000, 2000); // 生命长度(毫秒)
  private begin_alpha = rand(50, 100) / 100; // 初始透明度
  private begin_speed: number // // 初速度;
  private velocity_x: number;
  private velocity_y: number;

  readonly world: World;
  private x: number;
  private y: number;
  private coords: Coords = new Coords();

  private alpha = this.begin_alpha;
  private friction: number;
  private hue: number;
  private brightness = rand(50, 80);
  private wind: number;
  private line_width: any;
  private radius: number = 0;
  private anti_gravity_factor: number = 0.8;
  private get_decay(dt: number) {
    return this.begin_alpha * (dt / this.lifetime)
  };
  private get_gravity(dt: number) {
    return this.world.gravity * this.anti_gravity_factor * dt;
  }
  constructor(world: World, x: number, y: number, hue: number) {
    this.world = world;
    this.x = x;
    this.y = y;
    this.coords.init(x, y, 5)

    this.friction = world.air_friction_factor;
    const min_sp = Math.max(world.part_sp - world.part_sp_variance, 0);
    const max_sp = world.part_sp + world.part_sp_variance
    this.begin_speed = rand(min_sp, max_sp);

    const radians = rand(0, 360) * Math.PI / 180;
    this.velocity_x = Math.cos(radians) * this.begin_speed;
    this.velocity_y = Math.sin(radians) * this.begin_speed + this.get_gravity(1);
    this.hue = rand(hue - world.hue_variance, hue + world.hue_variance);
    this.wind = (rand(0, world.wind) - (world.wind / 2)) / 25;
    this.line_width = world.line_width;
  }

  private tick: number = 0
  update(dt: number) {
    this.tick += dt
    if (this.tick > 16) {
      this.coords.forward(this.x, this.y)
      this.tick = 0;
    }

    this.velocity_x *= 1 - this.friction * dt;
    this.velocity_y += this.get_gravity(1);
    this.velocity_y *= 1 - this.friction * dt;
    this.x += this.velocity_x * dt;
    this.y += this.velocity_y * dt;
    this.alpha -= this.get_decay(dt);

    if (!hit_test(0, 0, this.world.width, this.world.height, this.x - this.radius, this.y - this.radius, this.radius * 2, this.radius * 2) || this.alpha < .05) {
      this.world.particles.delete(this);
    }
  }
  draw(ctx: CanvasRenderingContext2D) {
    this.coords.random_curve(ctx, this.x, this.y)
    ctx.lineWidth = this.line_width;
    ctx.strokeStyle = 'hsla(' + this.hue + ', 100%, ' + this.brightness + '%, ' + this.alpha + ')';
    ctx.stroke();

    if (this.world.flicker_density > 0) {
      var inverseDensity = 50 - this.world.flicker_density;
      if (rand(0, inverseDensity) === inverseDensity) {
        ctx.beginPath();
        ctx.arc(Math.round(this.x), Math.round(this.y), rand(this.line_width, this.line_width + 3) / 2, 0, Math.PI * 2, false);
        ctx.closePath();
        var randAlpha = rand(50, 100) / 100;
        ctx.fillStyle = 'hsla(' + this.hue + ', 100%, ' + this.brightness + '%, ' + randAlpha + ')';
        ctx.fill();
      }
    }
  };
}
